<?php
/**
 * 收集一批工具方法供controller和model使用
 * @文件名称: Utility.php
 * @author: jawei
 * @Email: gaozhiwei@etcp.cn
 * @Date: 2017-06-06
 * @Copyright: 2017 悦畅科技有限公司. All rights reserved.
 * 注意：本内容仅限于悦畅科技有限公司内部传阅，禁止外泄以及用于其他的商业目的
 */
namespace app\common;
use Yii;
use yii\base\ErrorException;
class Utility
{
    /**
     * 检查字符串是否为手机号, 粗粒度监测
     *
     * @param  $val string  被测的字符串
     * @return boolean
     */
    public static function checkMobile($mobile)
    {
        if( is_numeric($mobile) && preg_match('/^13[0-9]{9}$|^14[0-9]{9}$|^15[0-9]{9}$|^17[0-9]{9}$|^18[0-9]{9}$/', $mobile))
        {
            return True;
        }
        return False;
    }

    /**
     * 检查字符串是否为电信手机号,粗粒度监测
     *
     * @param  $val string  被测的字符串
     * @return boolean
     */
    public static function checkTelecomMobile($mobile)
    {
        if( is_numeric($mobile) && preg_match('/^133[0-9]{8}$|^153[0-9]{8}$|^180[0-9]{8}$|^189[0-9]{8}$|^181[0-9]{8}$|^177[0-9]{8}$/', $mobile))
        {
            return True;
        }
        return False;
    }

    /**
     * 发送手机短信验证码。
     * @param  integer  $mobile  手机号
     * @param  string   $code    验证码
     * @param  integer  $minutes 过期时间, 单位分钟
     * @return boolean  是否发送成功
     */
    public static function sendVerifyCode($mobile, $code, $minutes = 5)
    {
        // 直接调用短信商, 保险起见, 只切5分之1的量 rand(0,4) == 0 || YII_ENV != 'prod'
        // 大汉三通切服, 临时全量切到常青处
        if (False)
        {
            $message = '您的活动验证码是：' . $code . '，有效期' . $minutes . '分钟，如非本人操作请忽略。';
            $return = Sms::sendOne($mobile, $message);
            if (is_array($return) && isset($return['errno']) && $return['errno'] == 0)
            {
                return True;
            }
        }
        $smsDomain = Yii::$app->params['smsDomain'];
        $url = 'http://' . $smsDomain . '/m/template/oneBackup';
        $url = 'http://' . $smsDomain . '/m/template/another';
        // $url = 'http://' . $smsDomain . '/m/template/anotherBackup';
        $replace = 'verifyCode=' . $code . '&min=' . $minutes;
        $param = array('mobile' => $mobile, 'code' => 1, 'params' => $replace);

        try
        {
            $json = self::curlRequest('post', $url, $param);
        }
        catch (ErrorException $e)
        {
            Yii::error('CURLException: Send Verify Code To ' . $mobile . ' Failed, Intf:' . $url . ', Error:' . $e->getMessage(), 'activity-send-sms');
            return False;
        }

        $return = json_decode($json, True);
        if (is_array($return) && $return['ret'] == 0)
        {
            return True;
        }
        else
        {
           Yii::error('Send Verify Code To ' . $mobile . ' Failed,' . $return['msg'], 'activity-send-sms');
        }
        return False;
    }

    /**
     * 短信提醒写入redis队列
     * @param  integer  $mobile      手机号
     * @param  invteger $code        模板编号, 比如 : 3 4 5
     * @param  array    $variables   模板变量参数 比如: ['money' => 10, 'min' => 5]
     * @return boolean  写入队列是否成功
     * @modify by lxq   20150907
     */
    public static function sendNotice($mobile, $code, $variables)
    {
        //启用异步发送机制
        //return self::realSendNotice($mobile, $code, $variables);
        // 待发送短信列表
        $code = intval($code);
        $task_key = 'list:Daemonsendnotice:push:' . $code;
        $task = json_encode(array('m'=>$mobile,'c'=>$code,'v'=>$variables));

        $redis = Yii::$app->redis;
        try
        {
            $redis->LPUSH($task_key,$task);
        }
        catch(yii\db\Exception $e)
        {
            Yii::error('RedisException, Send notice To ' . $mobile . ' Failed,error:'.$e->getMessage().',task:' . $task, 'activity-send-notice');
            return false;
        }
        return true;
    }
    /**
     * 发送短信通知
     *
     * @param  integer $mobile 手机号
     * @param  string  $message 短信内容
     * @return boolean 发送状态
     */
    public static function sendSms($mobile, $message, $alert = False)
    {
        if ($alert)
        {
            $smsDomain = Yii::$app->params['alertDomain'];
            $url = 'http://' . $smsDomain . '/m/template/itemBackup';
        }
        else
        {
            $smsDomain = Yii::$app->params['smsDomain'];
            $url = 'http://' . $smsDomain . '/m/template/itemAnother';
        }
        $param = array('mobile' => $mobile, 'message' => $message);

        try
        {
            $json = self::curlRequest('post', $url, $param);
        }
        catch (ErrorException $e)
        {
            Yii::error('CURLException: Send Sms To ' . $mobile . ' Failed, Intf:' . $url . ', Error:' . $e->getMessage(), 'activity-send-sms');
            return False;
        }

        $return = json_decode($json, True);
        if (is_array($return) && $return['ret'] == 0)
        {
            return True;
        }
        else
        {
           Yii::error('Send Sms To ' . $mobile . ' Failed,' . $return['msg'], 'activity-send-sms');
        }
        return False;
    }

    /**
     * 发送APNS消息通知
     *
     * @param  integer $to  手机号或者uuid
     * @param  string  $message 短信内容
     * @param  array   ['subtype'=> 303, 'h5Url'=>'xxx']  => {"ext":{"productID":"4833637868419235840001","subtype":"303"}}
     * @return boolean 发送状态
     */
    public static function sendPush($to, $message, $ext = array())
    {
        // 测试机的IP地址, 线上需要切换之
        $ext = json_encode(array('ext' => $ext));
        $pushDomain = Yii::$app->params['pushDomain'];
        $url = 'http://' . $pushDomain . '/m/push/one';
        if (!self::checkMobile($to))
        {
            $param = array('memberID' => $to, 'message' => $message, 'ext' => $ext);
        }
        else
        {
            $param = array('mobile' => $to, 'message' => $message, 'ext' => $ext);
        }

        try
        {
            $json = self::curlRequest('post', $url, $param);
        }
        catch (ErrorException $e)
        {
            // 以后改为 throw exception的方式
            Yii::error('Send Push To ' . $to . ' Failed, Error:' . $e->getMessage(), 'activity-send-push');
            return False;
        }

        $return = json_decode($json, True);
        if (is_array($return) && $return['ret'] == 0)
        {
            return True;
        }
        else
        {
            Yii::error('Send Push To ' . $to . ' Failed, Json:' . $json, 'activity-send-push');
        }
        return False;
    }

    /**
     * 地推、拉新用户操作日志, 方便统计和可视化
     *
     * 主要记录: when、who、what、how
     *
     * @return boolean
     */
    public static function doOperate($who, $what, $context = array())
    {
        $context['server'] = self::getLocalIp();
        if (php_sapi_name() != 'cli')
        {
            if(isset($_SERVER["HTTP_USER_AGENT"]))
            {
                $request = Yii::$app->getRequest();
                $context['client'] = $request->getUserIP();
                $context['ua'] = $_SERVER["HTTP_USER_AGENT"];
            }
            else
            {
                $context['client'] = '127.0.0.1';
                $context['ua'] = 'Unkown';
            }
        }
        $timestamp = microtime(True);
        $microseconds = 0;
        if (strpos($timestamp, '.') !== False)
        {
            $microseconds = substr($timestamp, strpos($timestamp, '.') + 1);
        }
        $timestamp = date('c', $timestamp);
        if (strpos($timestamp, '+') !== False && $microseconds != 0)
        {
            $timestamp = substr($timestamp, 0, strpos($timestamp, '+')) . '.' . $microseconds . substr($timestamp, strpos($timestamp, '+'));
        }
        $message = ['@timestamp' => $timestamp, 'who' => $who, 'what' => $what, 'context' => $context];
        $logFile = Yii::$app->getRuntimePath() . '/logs/operation-' . date('Ymd') . '.log';
        $chmod = False;
        if (!file_exists($logFile))
        {
            $chmod = True;
        }
        $message = json_encode($message) . PHP_EOL;
        file_put_contents($logFile, $message, FILE_APPEND);
        if ($chmod)
        {
            chmod($logFile, 0777);
        }
        return True;
    }
    /**
     * 获取指定日期对应的期次
     * @param $date 可以为空,如果为空则为当前日期
     * @return string 返回当前其次 格式如:001,012
     */
    public static function getRenmaiLotteryNo($date = null)
    {
        $startWeekOfYear = date("W", strtotime(Yii::$app->params['rmwStartDate']));
        $afterEightOfSunday = FALSE;
        if (is_null($date)) {
            $time = time();
        }else {
            $time = strtotime($date);
        }
        $endWeekOfYear = date("W",$time);
        if(date('w', $time) == 0 && date('H', $time) >= 20) {
            $afterEightOfSunday = TRUE;
        }
        if ($afterEightOfSunday == TRUE) {
            return substr('000' . ($endWeekOfYear - $startWeekOfYear + 2), -3);
        }else{
            return substr('000' . ($endWeekOfYear - $startWeekOfYear + 1), -3);
        }
    }
    /**
     * 借助CURL模拟HTTP接口调用
     *
     * @param  string  method  请求方法
     * @param  string  url     接口地址
     * @param  array   param   请求参数
     * @param  array   header  其他HTTP请求头
     * @param  integer timeout 响应超时时间
     * @return string  response
     */
    public static function curlRequest($method, $url, $param = array(), $header = array(), $timeout = 5)
    {
        $defaults = [
            CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 RRX Agent',
            CURLOPT_HEADER => 0,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_CONNECTTIMEOUT => $timeout,
            CURLOPT_TIMEOUT => $timeout
        ];

        $options = [];

        if (sizeof($header) > 0) {
            $options[CURLOPT_HTTPHEADER] = $header;
        }

        if (strtolower($method) == 'post') {
            $options[CURLOPT_URL] = $url;
            $options[CURLOPT_POST] = 1;
            if (is_array($param)) {
                $options[CURLOPT_POSTFIELDS] = http_build_query($param);
            } else {
                $options[CURLOPT_POSTFIELDS] = $param;
            }
        } else {
            if (strpos($url, '?') !== False) {
                $options[CURLOPT_URL] = $url . '&' . http_build_query($param);
            } else {
                $options[CURLOPT_URL] = $url . '?' . http_build_query($param);
            }
        }
        $ch = curl_init();
        curl_setopt_array($ch, ($options + $defaults));

        if(!$result = curl_exec($ch)) {
            $errno = curl_errno($ch);
            throw new ErrorException("Curl error [$errno]: " . curl_error($ch));
        }
        curl_close($ch);
        return $result;
    }

    /**
     * 校验签名
     *
     * @param  array   args   Http请求参数
     * @param  string  secret 签名秘钥
     * @return boolean
     */
    public static function checkSign($args, $secret)
    {
        if(isset($args['sign']))
        {
            $oldSign = $args['sign'];
            unset($args['sign']);
        }
        else
        {
            $oldSign = '';
        }
        ksort($args);
        $requestString = '';
        foreach($args as $k=>$v)
        {
            $requestString .= '|' . $v;
        }
        $requestString = trim($requestString, '|');
        $newSign = md5($requestString . '|' . $secret);
        if($oldSign == $newSign)
        {
            return True;
        }
        return False;
    }

    /**
     * 生成签名
     * @param  array $args  请求参数数组
     * @param  string $secret 签名秘钥
     * @return string  $sign 生成的签名
     */
    public static function createSign($args, $secret)
    {
        ksort($args);
        $requestString = '';
        foreach($args as $v)
        {
            $requestString .= '|' . $v;
        }
        $requestString = trim($requestString, '|');
        $sign = md5($requestString . '|' . $secret);
        return $sign;
    }
    /**
      * @desc:判断是否是安卓的ua访问
    */
    public static function isAndroidUA()
    {
        if(isset($_SERVER["HTTP_X_WAP_PROFILE"]))
        {
            return true;
        }

        if(preg_match("/wap\.|\.wap/i",$_SERVER["HTTP_ACCEPT"]))
        {
            return true;
        }

        if(isset($_SERVER["HTTP_USER_AGENT"]))
        {
            $user_agents = array("android", "midp", "j2me", "avantg", "docomo", "novarra", "palmos", "palmsource", "240x320", "opwv", "chtml", "pda", "windows\ ce", "mmp\/", "blackberry", "mib\/", "symbian", "wireless", "nokia", "hand", "mobi", "phone", "cdm", "up\.b", "audio", "SIE\-", "SEC\-", "samsung", "HTC", "mot\-", "mitsu", "sagem", "sony", "alcatel", "lg", "erics", "vx", "NEC", "philips", "mmm", "xx", "panasonic", "sharp", "wap", "sch", "rover", "pocket", "benq", "java", "pt", "pg", "vox", "amoi", "bird", "compal", "kg", "voda", "sany", "kdd", "dbt", "sendo", "sgh", "gradi", "jb", "\d\d\di", "moto");
            foreach($user_agents as $user_string)
            {
                if(preg_match("/".$user_string."/i",$_SERVER["HTTP_USER_AGENT"]))
                {
                    return true;
                }
            }
        }

        if(preg_match("/iphone/i",$_SERVER["HTTP_USER_AGENT"]))
        {
            return false;
        }
        return false;
    }

    /**
     * 跟电信ISP交互 二进制加密串转16进制加密串
     * @param string $data
     */
    public static function encodeBytes($data) {
        $split = str_split($data);
        foreach ($split as $byte)
        {
            $encrypt[] = chr(((ord($byte) >> 4) & 0xF) + ord('a'));
            $encrypt[] = chr((ord($byte) & 0xF) + ord('a'));
        }
        return implode($encrypt);
    }
    // 发送监控点
    public static function sendMetric($name, $value)
    {
        $port = '2003';
        $server = '100.126.1.36';
        $time = time();
        $cmd = "echo \"devops.gauges.laxin.${name} ${value} ${time}\" | nc ${server} ${port}";
        echo exec($cmd);
        return True;
    }
}

?>
